package com.xushi.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.xushi.bean.AlipayConfig;
import com.xushi.bean.OrderState;
import com.xushi.model.Template;
import com.xushi.model.TemplateOrder;
import com.xushi.model.TimePriceMap;
import com.xushi.service.AlipayService;
import com.xushi.service.TemplateOrderService;
import com.xushi.service.TemplateService;
import com.xushi.service.TimePriceMapService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;

@Service("alipayService")
public class AlipayServiceImpl implements AlipayService {

    public static Logger logger = LoggerFactory.getLogger(AlipayServiceImpl.class);


    @Autowired
    AlipayConfig alipayConfig;

    @Autowired
    TemplateService templateService;

    @Autowired
    TimePriceMapService timePriceMapService;

    @Autowired
    TemplateOrderService templateOrderService;

    AlipayClient alipayClient;

    private static final String timeoutExpress = "2m";

    @PostConstruct
    public void init() {
        alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(), alipayConfig.getAPP_ID(),
                alipayConfig.getRSA_PRIVATE_KEY(), "json", alipayConfig.getCHARSET(),
                alipayConfig.getALIPAY_PUBLIC_KEY(), alipayConfig.getSignType());
    }

    public String pay(int templateId, String timeId, String username) throws AlipayApiException {
        Template template = templateService.getTemplateById(templateId);
        if (ObjectUtils.isEmpty(template)) {
            throw new RuntimeException("invalid template id");
        }
        TimePriceMap timePrice = timePriceMapService.findByTemplateIdAndTimeId(String.valueOf(templateId), timeId);
        String totalAmount = timePrice.getPrice();

        String tpId = timePrice.getTimeId();
        String productCode = String.valueOf(templateId).concat(tpId);

        String subject = template.getName();
        String body = template.getDescription();
        int state = OrderState.UNPAID.ordinal();
        TemplateOrder templateOrder = templateOrderService.createOrder(username, subject, totalAmount, body,
                timeoutExpress, productCode, state);
        String form = pay0(String.valueOf(templateOrder.getId()), subject, totalAmount, body,
                timeoutExpress, productCode);
        return form;
    }

    public String pay0(String outTradeNo, String subject, String totalAmount, String body, String timeoutExpress,
                       String productCode) throws AlipayApiException {

        AlipayTradeWapPayRequest wapPayRequest = new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel wapPayModel = new AlipayTradeWapPayModel();
        wapPayModel.setOutTradeNo(outTradeNo);
        wapPayModel.setSubject(subject);
        wapPayModel.setTotalAmount(totalAmount);
        wapPayModel.setBody(body);
        wapPayModel.setTimeoutExpress(timeoutExpress);
        wapPayModel.setProductCode(productCode);
        wapPayRequest.setBizModel(wapPayModel);
        // 设置异步通知地址
        wapPayRequest.setNotifyUrl(alipayConfig.getNOTIFY_URL());
        // 设置同步地址
        wapPayRequest.setReturnUrl(alipayConfig.getRETURN_URL());

        // form表单生产
        String form = "";

        // 调用SDK生成表单
        form = alipayClient.pageExecute(wapPayRequest).getBody();
        return form;
    }

    public boolean verify(HashMap<String, String> params) throws AlipayApiException {

        boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getALIPAY_PUBLIC_KEY(), alipayConfig.getCHARSET(),
                alipayConfig.getSignType());
        return verifyResult;
    }

    public void notify(HashMap<String, String> params) {

        // 商户订单号
        String out_trade_no = params.get("out_trade_no");
        // 支付宝交易号
        String trade_no = params.get("trade_no");
        // 交易状态
        String trade_status = params.get("trade_status");

        logger.info("notify params:" + params);

        // 请在这里加上商户的业务逻辑程序代码

        if (trade_status.equals("TRADE_FINISHED")) {
            // 判断该笔订单是否在商户网站中已经做过处理
            // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
            // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
            // 如果有做过处理，不执行商户的业务程序

            // 注意：
            // 如果签约的是可退款协议，退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            // 如果没有签约可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            logger.info("trade finished: " + out_trade_no);

        } else if (trade_status.equals("TRADE_SUCCESS")) {
            // 判断该笔订单是否在商户网站中已经做过处理
            // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
            // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
            // 如果有做过处理，不执行商户的业务程序

            // 注意：
            // 如果签约的是可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
            TemplateOrder order = templateOrderService.findOrderById(Integer.valueOf(out_trade_no));
            order.setState(OrderState.PAID.ordinal());
            templateOrderService.updateOrder(order);

            // TODO 把createUserTemplate放到这里
        }
    }

    public String query(String outTradeNo, String tradeNo) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getServerUrl(), alipayConfig.getAPP_ID(),
                alipayConfig.getRSA_PRIVATE_KEY(), "json", alipayConfig.getCHARSET(),
                alipayConfig.getALIPAY_PUBLIC_KEY(), alipayConfig.getSignType());

        AlipayTradeQueryRequest tradeQueryRequest = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel tradeQueryModel = new AlipayTradeQueryModel();
        tradeQueryModel.setOutTradeNo(outTradeNo);
        tradeQueryModel.setTradeNo(tradeNo);
        tradeQueryRequest.setBizModel(tradeQueryModel);

        AlipayTradeQueryResponse alipayResponse = alipayClient.execute(tradeQueryRequest);
        String responseBody = alipayResponse.getBody();
        return responseBody;
    }


}
